import pygame
from pygame import mixer
import sys

from settings import Settings
from paddle import PaddleLeft, PaddleRight
from ball import Ball
from time import sleep
from scoreboard import ScoreBoard
from button import Button

# 加载背景图片

class Pong:
    ''' 游戏主类 '''

    def __init__(self):
        pygame.init()  # 初始化所有pygame模块
        self.settings = Settings()  # 创建设置对象
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))  # 创建显示窗口
        self.font=pygame.font.Font('./image/font.ttf',180)
        # 全屏模式，取消注释以启用
        # self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)

        pygame.display.set_caption('Pong')  # 设置窗口标题
        self.settings.screen_width = self.screen.get_rect().width  # 更新屏幕宽度
        self.settings.screen_height = self.screen.get_rect().height  # 更新屏幕高度

        self.scoreboard = ScoreBoard(self)  # 创建记分板对象
        self.button = Button(self, 'Play')  # 创建带有文本的按钮

        self.paddle_left = PaddleLeft(self)  # 创建左侧球拍
        self.paddle_right = PaddleRight(self)  # 创建右侧球拍
        self.ball = Ball(self)  # 创建球对象

        self.playing = False  # 标志，False表示显示播放按钮，True表示游戏进行中

        self.clock = pygame.time.Clock()  # 创建时钟对象

        # 加载音效
        self.border_sound = mixer.Sound('audio/wall.mp3')
        self.paddle_sound = mixer.Sound('audio/paddle.mp3')
        self.goal_sound = mixer.Sound('audio/score.mp3')

    def main(self):
        ''' 主游戏循环 '''
        while True:
            self._check_events()  # 检查事件

            if self.playing:
                self._update_paddle()  # 更新球拍位置
                self._ball_update()  # 更新球位置
            self._update_screen()  # 更新屏幕内容
            if(self.settings.player_left_score>3 or self.settings.player_right_score>3):
                self._show_game_over()

            pygame.display.flip()  # Refresh screen

            self.clock.tick(self.settings.FPS)  # FPS

    def _check_events(self):
        ''' 检查键盘和鼠标事件 '''
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 退出游戏
                sys.exit()
            elif event.type == pygame.KEYDOWN:  # 按键按下
                self._check_event_keydown(event)
            elif event.type == pygame.KEYUP:  # 按键释放
                self._check_event_keyup(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:  # 鼠标按钮点击
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

    def _check_event_keydown(self, event):
        ''' 键盘按键按下事件 '''
        # 左侧球拍移动
        if event.key == pygame.K_w:
            self.paddle_left.moving_up = True
        elif event.key == pygame.K_s:
            self.paddle_left.moving_down = True

        # 右侧球拍移动
        elif event.key == pygame.K_UP:
            self.paddle_right.moving_up = True
        elif event.key == pygame.K_DOWN:
            self.paddle_right.moving_down = True

        # 退出游戏的替代方式
        elif event.key == pygame.K_q:
            sys.exit()

        # 鼠标点击的替代方式
        elif event.key == pygame.K_p:
            self.playing = True
            pygame.mouse.set_visible(False)

    def _check_event_keyup(self, event):
        ''' 键盘按键释放事件 '''
        if event.key == pygame.K_w:
            self.paddle_left.moving_up = False
        elif event.key == pygame.K_s:
            self.paddle_left.moving_down = False

        elif event.key == pygame.K_UP:
            self.paddle_right.moving_up = False
        elif event.key == pygame.K_DOWN:
            self.paddle_right.moving_down = False

    def _check_play_button(self, mouse_pos):
        ''' 检查鼠标点击是否与播放按钮碰撞 '''
        button_clicked = self.button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.playing:
            self.playing = True
            pygame.mouse.set_visible(False)  # 隐藏鼠标光标

    def _update_paddle(self):
        ''' 移动球拍 '''
        self.paddle_right.update()
        self.paddle_left.update()

    def _ball_update(self):
        ''' 移动球并检查与边界和球拍的碰撞 '''
        # 检查与边界的碰撞
        if self.ball.check_borders():
            self.ball.direction_y *= -1
            self.border_sound.play()

        # 检查与球拍的碰撞
        self._collission_ball_paddle()

        # 检查进球
        self._collission_end_border()

        self.ball.update()

    def _reset(self):
        ''' 重置球拍和球 '''
        self.paddle_left.reset_paddle()
        self.paddle_right.reset_paddle()
        self.settings.reset_settings()
        self.ball.reset_ball()
        self.ball.direction_y = self.ball.ball_direction()
        sleep(1)  # 暂停游戏1秒

    def _collission_ball_paddle(self):
        ''' 检查球与球拍的碰撞 '''
        # 左球拍与球的碰撞，返回True或False
        ball_left_paddle_collission = ((self.ball.ball_pos_x <= self.paddle_left.rect.right) and
                                       (self.ball.ball_pos_x >= self.paddle_left.rect.left) and
                                       (self.ball.ball_pos_y <= self.paddle_left.rect.bottom) and
                                       (self.ball.ball_pos_y >= self.paddle_left.rect.top))

        # 右球拍与球的碰撞，返回True或False
        ball_right_paddle_collission = ((self.ball.ball_pos_x <= self.paddle_right.rect.right) and
                                        (self.ball.ball_pos_x >= self.paddle_right.rect.left) and
                                        (self.ball.ball_pos_y <= self.paddle_right.rect.bottom) and
                                        (self.ball.ball_pos_y >= self.paddle_right.rect.top))

        # 当球与球拍碰撞时
        if ball_left_paddle_collission or ball_right_paddle_collission:
            # 播放音效
            self.paddle_sound.play()

            self.ball.direction_x *= -1  # 改变球的水平方向
            self.ball.direction_y = self.ball.ball_direction()  # 随机改变球的垂直方向
            self.settings.speedup_ball()  # 加速游戏

    def _collission_end_border(self):
        ''' 当进球时 '''
        left_border = self.ball.ball_pos_x <= 0
        right_border = self.ball.ball_pos_x >= self.settings.screen_width

        # 右侧玩家得分
        if left_border:
            self._left_border_collission()
        # 左侧玩家得分
        elif right_border:
            self._right_border_collission()

    def _right_border_collission(self):
        ''' 左侧玩家得分 '''
        self.goal_sound.play()
        self.settings.player_left_score += 1
        self.scoreboard.prep_score_player_left()
        self.ball.direction_x = -abs(self.ball.direction_x)
        self._reset()

    def _left_border_collission(self):
        ''' 右侧玩家得分 '''
        self.goal_sound.play()
        self.settings.player_right_score += 1
        self.scoreboard.prep_score_player_right()
        self.ball.direction_x = abs(self.ball.direction_x)
        self._reset()

    def _show_game_over(self):
        ''' Display Game Over message and exit '''
        game_over_text = self.font.render("Game Over", True, (255, 0, 0))
        self.screen.blit(game_over_text, (250, 250))
        pygame.display.flip()
        sleep(2)  # Wait for 2 seconds
        pygame.quit()
        sys.exit()

    def _update_screen(self):
        ''' Draw everything to the screen '''
        self.screen.fill(self.settings.bg_color)  # background
        self._draw_middle_line()
        self.ball.draw_ball()
        self.paddle_left.draw_paddle()
        self.paddle_right.draw_paddle()
        self.scoreboard.show_score()
    def _update_screen(self):
        ''' 绘制所有内容到屏幕 '''

        self.screen.blit(self.settings.image, (0, 0))  # 绘制背景图片

        self._draw_middle_line()  # 绘制中线
        self.ball.draw_ball()  # 绘制球
        self.paddle_left.draw_paddle()  # 绘制左球拍
        self.paddle_right.draw_paddle()  # 绘制右球拍
        self.scoreboard.show_score()  # 显示得分

        # 如果没有在游戏中，绘制播放按钮
        if not self.playing:
            self.screen.blit(self.settings.rul, (0, 0))
            self.button.draw_button()

        pygame.display.flip()  # 刷新屏幕

        self.clock.tick(self.settings.FPS)  # 设置帧率

    def _draw_middle_line(self):
        ''' 绘制屏幕中间的线 '''
        COLOR = self.settings.middle_line_color  # 线的颜色
        WIDTH = self.settings.middle_line_width  # 线的宽度

        # 线的起点在屏幕顶部中央
        START_POS = (self.settings.screen_width // 2, 0)
        # 线的终点在屏幕底部中央
        END_POS = (self.settings.screen_width // 2, self.settings.screen_height)

        pygame.draw.line(self.screen, COLOR, START_POS, END_POS, WIDTH)  # 绘制线条


if __name__ == '__main__':
    pong = Pong()  # 创建Pong游戏对象
    pong.main()  # 启动游戏
